home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Pascal / Snippets / DimText Pascal 1.0 / Dim_text.p < prev    next >
Encoding:
Text File  |  1995-04-18  |  10.4 KB  |  352 lines  |  [TEXT/PJMM]

  1. unit Dim_text;
  2.  
  3. interface
  4.  
  5.     uses
  6.         Appletalk, CTBUtilities;
  7.  
  8.     procedure Init_dimmer (dp: DialogPtr);
  9.     procedure Dispose_dimmer (dp: DialogPtr);
  10.     procedure New_dimmables (dp: DialogPtr);
  11.     procedure Dispose_dimmables (dp: DialogPtr);
  12.     procedure Dim_text (dp: DialogPtr; item: Integer; dim: Boolean);
  13.  
  14. {     ---------------------------------------------------------------------}
  15. {    Dim_text            This is a group of routines for dimming text}
  16. {                        items in dialogs.  As is, it assumes that you are}
  17. {                        not using the dialog's refCon for anything else,}
  18. {                        and that you are not using the QuickDraw}
  19. {                        bottlenecks for anything else.}
  20. {    }
  21. {    This code can be used freely.  I ask that you tell me about any}
  22. {    improvements that you think of.}
  23. {    }
  24. {    James W. Walker        March 17, 1994}
  25. {    JWWalker@AOL.com}
  26. {    76367.2271@compuserve.com}
  27. {    --------------------------------------------------------------------- }
  28.  
  29. implementation
  30.  
  31. {$SETC SYSTEM_6_COMPATIBLE    := true}
  32.  
  33.     procedure Dim_text_proc (byteCnt: Integer; textAddr: Ptr; numerPt: Point; denomPt: Point);
  34.     forward;
  35.  
  36.     type
  37.         Dim_list_el_Ptr = ^Dim_list_el;
  38.         Dim_list_el = record
  39.                 item_num: Integer;
  40.                 next: Dim_list_el_Ptr;
  41.                 bounds: Rect;
  42.                 dim: Boolean;
  43.                 editable: Boolean;
  44.             end;
  45.  
  46.     type
  47.         Dim_data = record
  48.                 dim_list: Dim_list_el_Ptr;
  49.                 Old_text_proc: ProcPtr;{QDTextUPP}
  50. {$IFC SYSTEM_6_COMPATIBLE}
  51.                 has_gray_text: Boolean;
  52.                 has_CountDITL: Boolean;
  53. {$ENDC}
  54.             end;
  55.         DimDataPtr = ^Dim_data;
  56.  
  57.  
  58. {     ---------------------------------------------------------------------}
  59. {    Get_dim_data        Macro to get the list head.}
  60. {                        Just used to encapsulate the use of the refCon,}
  61. {                        so that if you need to store the list head}
  62. {                        somewhere else you will only need to change this}
  63. {                        and Init_dimmer.}
  64. {    --------------------------------------------------------------------- }
  65.  
  66.     function Get_dim_data (dp: DialogPtr): DimDataPtr;
  67.     begin
  68.         Get_dim_data := DimDataPtr(WindowPeek(dp)^.refCon);
  69.     end;
  70.  
  71. {     ---------------------------------------------------------------------}
  72. {    Init_dimmer        Set up a dialog for dimming text.  Call it once, soon}
  73. {                    after creating the dialog.}
  74. {    --------------------------------------------------------------------- }
  75.  
  76.     procedure Init_dimmer (dp: DialogPtr);
  77.         var
  78.             dim_data_p: DimDataPtr;
  79.             qd_procs: QDProcsPtr;
  80.             val: LongInt;
  81.     begin
  82.         dim_data_p := DimDataPtr(NewPtrClear(sizeof(Dim_data)));
  83.         if (dim_data_p <> nil) then
  84.             begin
  85.         { Store the pointer where we can find it later}
  86.                 WindowPeek(dp)^.refCon := LongInt(dim_data_p);
  87.  
  88.         { Patch the QuickDraw bottleneck for text}
  89.                 if BitAnd(dp^.portBits.rowBytes, $8000) = 0 then    { B&W port}
  90.                     begin
  91.                         qd_procs := QDProcsPtr(NewPtrSysClear(sizeof(QDProcs)));
  92.                         SetStdProcs(qd_procs^);
  93.                     end
  94.                 else { color port}
  95.                     begin
  96.                         qd_procs := QDProcsPtr(NewPtrSysClear(sizeof(CQDProcs)));
  97.                         SetStdCProcs(CQDProcsPtr(qd_procs)^);
  98.                     end;
  99.                 dim_data_p^.Old_text_proc := qd_procs^.textProc;
  100.                 qd_procs^.textProc := @Dim_text_proc; {NewQDTextProc(}
  101.                 dp^.grafProcs := qd_procs;
  102.  
  103. {$ifc SYSTEM_6_COMPATIBLE}
  104.         { Which System 7 features are available?}
  105.                 dim_data_p^.has_gray_text := (Gestalt(gestaltQuickdrawFeatures, val) = noErr) and (BitAnd(val, BSL(1, gestaltHasGrayishTextOr)) <> 0);
  106.                 dim_data_p^.has_CountDITL := (Gestalt(gestaltDITLExtAttr, val) = noErr) and (BitAnd(val, BSL(1, gestaltDITLExtPresent)) <> 0);
  107. {$endc}
  108.  
  109.                 New_dimmables(dp);
  110.             end;
  111.     end; {Init_dimmer}
  112.  
  113. {     ---------------------------------------------------------------------}
  114. {    Dispose_dimmer        Called once after you are through with a dialog.}
  115. {    --------------------------------------------------------------------- }
  116.  
  117.     procedure Dispose_dimmer (dp: DialogPtr);
  118.         var
  119.             maybe_null: Ptr;
  120.     begin
  121.         Dispose_dimmables(dp);
  122.         maybe_null := Ptr(Get_dim_data(dp));
  123.         if (maybe_null <> nil) then
  124.             DisposePtr(maybe_null);
  125.         if (dp^.grafProcs <> nil) then
  126.             begin
  127. {DisposeRoutineDescriptor(qd_procs^.textProc);}
  128.                 DisposePtr(Ptr(dp^.grafProcs));
  129.             end;
  130.         dp^.grafProcs := nil;
  131.     end; {Dispose_dimmer}
  132.  
  133. {     ---------------------------------------------------------------------}
  134. {    Dim_text        Set the dimming state of a text item.}
  135. {    --------------------------------------------------------------------- }
  136.  
  137.     procedure Dim_text (dp: DialogPtr; item: Integer; dim: Boolean);
  138.         var
  139.             dim_head: DimDataPtr;
  140.             dimmable: Dim_list_el_Ptr;
  141.             iRect: Rect;
  142.             iHandle: Handle;
  143.             iType: Integer;
  144.             disable_flag: Integer;
  145.     begin
  146.         dim_head := Get_dim_data(dp);
  147.         if (dim_head <> nil) then
  148.             dimmable := dim_head^.dim_list;
  149.         { Try to find the right item number in the list.}
  150.         while ((dimmable <> nil) and (dimmable^.item_num <> item)) do
  151.             begin
  152.                 dimmable := dimmable^.next;
  153.             end;
  154.         if (dimmable <> nil) then    { found it...}
  155.             begin
  156.                 dimmable^.dim := dim;
  157.                 GetDItem(dp, item, iType, iHandle, iRect);
  158.                 if (dimmable^.editable) then
  159.  
  160.                 (*}
  161. {                    To dim an editable text item, we need to turn it}
  162. {                    into a static text item, and also take some care}
  163. {                    that it is not showing the insertion point or a}
  164. {                    selection range.}
  165. {                *)
  166.                     begin
  167.                         disable_flag := BAnd(iType, itemDisable);
  168.                         if dim then
  169.                             begin
  170.                                 TEDeactivate(DialogPeek(dp)^.textH);
  171.                                 if item = DialogPeek(dp)^.editField + 1 then
  172.                                     begin
  173.                                         SelIText(dp, item, 0, 0);
  174.                                         DialogPeek(dp)^.editField := -1;
  175.                                     end;
  176.                                 SetDItem(dp, item, BitOr(statText, disable_flag), iHandle, iRect);
  177.                                 DialogPeek(dp)^.editField := -1;
  178.                                 TEActivate(DialogPeek(dp)^.textH);
  179.                                 InvalRect(iRect);
  180.                             end
  181.                         else
  182.                             begin
  183.                                 SetDItem(dp, item, BitOr(editText, disable_flag), iHandle, iRect);
  184.                                 SelIText(dp, item, 0, 0);
  185.                                 EraseRect(iRect);
  186.                                 TEUpdate(iRect, DialogPeek(dp)^.textH);
  187.                             end;
  188.                     end
  189.                 else
  190.                     begin
  191.                         InvalRect(iRect);
  192.                     end;
  193.             end;
  194.     end; {Dim_text}
  195.  
  196.  
  197. (*    ---------------------------------------------------------------------}
  198. {    Dispose_dimmables        Dispose of the individual dimming items.}
  199. {                            This is called by Dispose_dimmer, so you will}
  200. {                            not ordinarily have to call it directly}
  201. {                            unless you are changing item lists}
  202. {                            dynamically using ShortenDITL and AppendDITL.}
  203. {    ---------------------------------------------------------------------}
  204. {*)
  205.     procedure Dispose_dimmables (dp: DialogPtr);
  206.         var
  207.             dim_head: DimDataPtr;
  208.             next: Dim_list_el_Ptr;
  209.     begin
  210.         dim_head := Get_dim_data(dp);
  211.         while (dim_head^.dim_list <> nil) do
  212.             begin
  213.                 EraseRect(dim_head^.dim_list^.bounds);
  214.                 next := dim_head^.dim_list^.next;
  215.                 DisposePtr(Ptr(dim_head^.dim_list));
  216.                 dim_head^.dim_list := next;
  217.             end;
  218.     end; {Dispose_dimmables}
  219.  
  220. {     ---------------------------------------------------------------------}
  221. {    New_dimmables            Makes all text items in the dialog dimmable,}
  222. {                            both static and editable text.  Called by}
  223. {                            Init_dimmer, so you would not normally need}
  224. {                            to call it directly.}
  225. {                            But if you change the item list using}
  226. {                            ShortenDITL and AppendDITL, you would call}
  227. {                            Dispose_dimmables before the change and call}
  228. {                            New_dimmables after the change.}
  229. {    --------------------------------------------------------------------- }
  230.  
  231.     procedure New_dimmables (dp: DialogPtr);
  232.         type
  233.             IntPtr = ^Integer;
  234.             IntHnd = ^IntPtr;
  235.         var
  236.             dim_head: DimDataPtr;
  237.             new_dim: Dim_list_el_Ptr;
  238.             iRect: Rect;
  239.             iHandle: Handle;
  240.             iType, item, max_item: Integer;
  241.     begin
  242.         dim_head := Get_dim_data(dp);
  243.         if dim_head <> nil then
  244.             begin
  245. {$ifc SYSTEM_6_COMPATIBLE}
  246.                 if dim_head^.has_CountDITL then
  247.                     begin
  248.                         max_item := CountDITL(dp);
  249.                     end
  250.                 else
  251.                     begin
  252.                         max_item := IntHnd(DialogPeek(dp)^.items)^^ + 1;
  253.                     end;
  254. {$elsec}
  255.                 max_item := CountDITL(dp);
  256. {$endc}
  257.  
  258.                 for item := max_item downto 1 do
  259.                     begin
  260.                         GetDItem(dp, item, iType, iHandle, iRect);
  261.                         if BitAnd(iType, BitOr(statText, editText)) <> 0 then
  262.                             begin
  263.                                 new_dim := Dim_list_el_Ptr(NewPtrClear(sizeof(Dim_list_el)));
  264.                                 if new_dim <> nil then
  265.                                     begin
  266.                                         new_dim^.next := dim_head^.dim_list;
  267.                                         dim_head^.dim_list := new_dim;
  268.                                         new_dim^.item_num := item;
  269.                                         new_dim^.editable := BAnd(iType, editText) <> 0;
  270.                                         new_dim^.bounds := iRect;
  271.                                         if (new_dim^.editable) then
  272.                                             begin
  273.                                                 InsetRect(new_dim^.bounds, -3, -3);
  274.                                             end;
  275.                                     end;
  276.                             end;
  277.                     end;
  278.             end;
  279.     end; {New_dimmables}
  280.  
  281.  
  282. {     ---------------------------------------------------------------------}
  283. {    Dim_text_proc            The QuickDraw bottleneck routine that does}
  284. {                            the actual dimming, and also draws the frame}
  285. {                            around dimmed editable text.}
  286. {    --------------------------------------------------------------------- }
  287.  
  288.     procedure MyCallQDTextProc (byteCnt: Integer; textAddr: Ptr; numerPt, denomPt: Point; myProc: ProcPtr);
  289.     inline
  290.         $205f,     {movea.l  (a7)+,a0        ; (a0) is a ptr to string, 4(a0) is mode}
  291.         $4e90;
  292.  
  293.     procedure Dim_text_proc (byteCnt: Integer; textAddr: Ptr; numerPt: Point; denomPt: Point);
  294.         var
  295.             item_num: Integer;
  296.             dp: DialogPtr;
  297.             dimmable: Dim_list_el_Ptr;
  298.             dim_head: DimDataPtr;
  299.             gray_rect: Rect;
  300.             save_clip: RgnHandle;
  301.             save_pen: PenState;
  302.     begin
  303.         GetPort(dp);
  304.         dim_head := Get_dim_data(dp);
  305.         item_num := FindDItem(dp, dp^.pnLoc) + 1;
  306.         dimmable := dim_head^.dim_list;
  307.         while ((dimmable <> nil) and (dimmable^.item_num <> item_num)) do
  308.             begin
  309.                 dimmable := dimmable^.next;
  310.             end;
  311.         if ((dimmable <> nil) and (dimmable^.dim)) then
  312.             begin
  313. {$ifc SYSTEM_6_COMPATIBLE}
  314.                 if dim_head^.has_gray_text then
  315. {$endc}
  316.                     begin
  317.                         TextMode(grayishTextOr);
  318.                     end;
  319.                 if dimmable^.editable then
  320.                     begin
  321.                         save_clip := NewRgn;
  322.                         GetClip(save_clip);
  323.                         ClipRect(dimmable^.bounds);
  324.                         FrameRect(dimmable^.bounds);
  325.                         SetClip(save_clip);
  326.                         DisposeRgn(save_clip);
  327.                     end;
  328.             end;
  329.  
  330.         MyCallQDTextProc(byteCnt, textAddr, numerPt, denomPt, dim_head^.Old_text_proc);
  331. {CallQDTextProc(dim_head^.Old_text_proc, byteCnt, textAddr, numerPt, denomPt);}
  332.  
  333. {$ifc SYSTEM_6_COMPATIBLE}
  334.         if (not dim_head^.has_gray_text and (dimmable <> nil) and dimmable^.dim) then
  335.             begin
  336.                 gray_rect := dimmable^.bounds;
  337.                 InsetRect(gray_rect, 1, 1);
  338.                 GetPenState(save_pen);
  339.                 PenMode(patBic);
  340. {             The reason I used a string literal rather than the QuickDraw}
  341. {            global gray is so that it can be used in a code resource}
  342. {            without problems. }
  343.  
  344. {        PenPat( (ConstPatternParam) '\xAA\x55\xAA\x55\xAA\x55\xAA\x55' ); Kanke StuffHex?}
  345.                 PenPat(gray);
  346.                 PaintRect(gray_rect);
  347.                 SetPenState(save_pen);
  348.             end;
  349. {$endc}
  350.     end;
  351.  
  352. end.